import 'package:flutter/material.dart';
import 'dart:math' as math;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
// 子组件大小超出了父组件大小时，如果不经过处理的话 Flutter 中就会显示一个溢出警告并在控制台打印错误日志

// 根据Flutter 的布局协议，父组件会将自身的最大显示空间作为约束传递给子组件，子组件应该遵守父组件的约束，如果子组件原始大小超过了父组件的约束区域，则需要进行一些缩小、裁剪或其它处理，

// const FittedBox({
//   Key? key,
//   this.fit = BoxFit.contain, // 适配方式
//   this.alignment = Alignment.center, //对齐方式
//   this.clipBehavior = Clip.none, //是否剪裁
//   Widget? child,
// })

// 1. FittedBox 在布局子组件时会忽略其父组件传递的约束，可以允许子组件无限大，即FittedBox 传递给子组件的约束为（0<=width<=double.infinity, 0<= height <=double.infinity）。
// 2. FittedBox 对子组件布局结束后就可以获得子组件真实的大小。
// 3. FittedBox 知道子组件的真实大小也知道他父组件的约束，那么FittedBox 就可以通过指定的适配方式（BoxFit 枚举中指定），让起子组件在 FittedBox 父组件的约束范围内按照指定的方式显示。

Widget wContainer(BoxFit boxFit) {
  // return Container(
  //   width: 50,
  //   height: 50,
  //   color: Colors.red,
  //   child: FittedBox(
  //     fit: boxFit,
  //     // 子容器超过父容器大小
  //     child: Container(width: 60, height: 70, color: Colors.blue),
  //   ),
  // );

  return ClipRect(
    // 将超出子组件布局范围的绘制内容剪裁掉
    child: Container(
      width: 50,
      height: 50,
      color: Colors.red,
      child: FittedBox(
        fit: boxFit,
        child: Container(width: 60, height: 70, color: Colors.blue),
      ),
    ),
  );
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text(title)),
        body: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
          wContainer(BoxFit
              .none), // 虽然 FittedBox 子组件的大小超过了 FittedBox 父 Container 的空间，**但FittedBox 自身还是要遵守其父组件传递的约束**，所以最终 FittedBox 的本身的大小是 50×50，这也是为什么蓝色会和下面文本重叠的原因，因为在布局空间内，父Container只占50×50的大小，接下来文本会紧挨着Container进行布局，而此时Container 中有子组件的大小超过了自己，所以最终的效果就是绘制范围超出了Container，但布局位置是正常的，所以就重叠了。如果我们不想让蓝色超出父组件布局范围，那么可以可以使用 ClipRect 对超出的部分剪裁掉即可：
          Text('Wendux'),
          wContainer(BoxFit.contain), // 按照子组件的比例缩放，尽可能多的占据父组件空间
          Text('Flutter中国'),

          //  MainAxisAlignment.spaceEvenly，这会将水平方向的的剩余显示空间均分成多份穿插在每一个 child之间。

          // 可以看到，当数字为'  90000000000000000  '时，三个数字的长度加起来已经超出了测试设备的屏幕宽度，所以直接使用 Row 会溢出，当给 Row 添加上如果加上 FittedBox时，就可以按比例缩放至一行显示，实现了我们预期的效果。但是当数字没有那么大时，比如下面的 ' 800 '，直接使用 Row 是可以的，但加上 FittedBox 后三个数字虽然也能正常显示，但是它们却挤在了一起，这不符合我们的期望。之所以会这样，原因其实很简单：在指定主轴对齐方式为 spaceEvenly 的情况下，Row 在进行布局时会拿到父组件的约束，如果约束的 maxWidth 不是无限大，则 Row 会根据子组件的数量和它们的大小在主轴方向来根据 spaceEvenly 填充算法来分割水平方向的长度，最终Row 的宽度为 maxWidth；但如果 maxWidth 为无限大时，就无法在进行分割了，所以此时 Row 就会将子组件的宽度之和作为自己的宽度. 当 Row 没有被 FittedBox 包裹时，此时父组件传给 Row 的约束的 maxWidth 为屏幕宽度，此时，Row 的宽度也就是屏幕宽度，而当被FittedBox 包裹时，FittedBox  传给 Row 的约束的 maxWidth 为无限大（double.infinity）
          Column(
            children: [
              wRow(' 90000000000000000 '),
              FittedBox(child: wRow(' 90000000000000000 ')),
              wRow(' 800 '),
              FittedBox(child: wRow(' 800 ')),
            ]
                .map((e) => Padding(
                      padding: EdgeInsets.symmetric(vertical: 20),
                      child: e,
                    ))
                .toList(),
          ),
          Column(
            children: [
              wRow(' 90000000000000000 '),
              SingleLineFittedBox(child: wRow(' 90000000000000000 ')),
              wRow(' 800 '),
              SingleLineFittedBox(child: wRow(' 800 ')),
            ]
                .map((e) => Padding(
                      padding: EdgeInsets.symmetric(vertical: 20),
                      child: e,
                    ))
                .toList(),
          ),
        ]));
  }
}

// 直接使用Row
Widget wRow(String text) {
  Widget child = Text(text);
  child = Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [child, child, child],
  );
  return child;
}

class SingleLineFittedBox extends StatelessWidget {
  const SingleLineFittedBox({Key? key, this.child}) : super(key: key);
  final Widget? child;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (_, constraints) {
        return FittedBox(
          child: ConstrainedBox(
            constraints: constraints.copyWith(
              //让 minWidth 使用屏幕宽度
              minWidth: constraints.maxWidth,
              maxWidth: double.infinity,
              //maxWidth: constraints.maxWidth
            ),
            child: child,
          ),
        );
      },
    );
  }
}
